package com.shop.cereshop.app.dl.logic.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.shop.cereshop.app.dl.logic.utils.YunUtil.Utils;
import com.shop.cereshop.app.redis.service.api.StringRedisService;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.*;

/**
 * @program: dlshop
 * 描述：
 * @author: 我好帅
 * @create: 2021-07-28 14:34
 **/
@Slf4j
public class GetFrontToken {

    final static String URL = "https://open.95516.com/open/access/1.0/frontToken";

    public static Map<String, String> getMap(String appid, String frontToken, String url) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("appId", appid);
        map.put("frontToken", frontToken);
        map.put("url", url);
// 16位随机字符串
        map.put("nonceStr", getRandomString(16));
// 以秒为单位
        map.put("timestamp", System.currentTimeMillis() / 1000 + "");
// 排序
        String signContent = getSignContent(map);
// 签名： appId、frontToken、nonceStr、 timestamp、url
        map.put("signature", sha256(signContent.getBytes()));
// 这个frontToken不需要传递给前端
        map.remove("frontToken");
        return map;
    }

    /**
     * 获取upsdk接口初始化数据
     *
     * @param frontToken
     * @return
     */
    public static String getMap3(String appId, String frontToken, String url, Gson gson) {


        //拼装参数Map
        Map<String, String> params = new HashMap<String, String>(0);
        params.put("appId", appId);

        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        params.put("timestamp", timestamp);

        //生成随即字符串
        String nonceStr = Utils.createNonceStr();
        params.put("nonceStr", nonceStr);

        //设置签名
        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put("appId", appId);//应用ID
        parameters.put("timestamp", timestamp);//时间戳
        parameters.put("nonceStr", nonceStr);//字符串
        //签名URL，示例为固定值，该值应在upsdk.config页面通过window.location.href方法获取
        parameters.put("url", url);
        parameters.put("frontToken", frontToken);// "2fHYL++fSeeY53Qbs1i7Cg=="
        String signature = Utils.createSign(parameters);//签名加密
        params.put("signature",
                signature);
        params.put("debug", "true");
        //返回数据
        String resultStr = gson.toJson(params);
        return resultStr;


    }

    /**
     * 获取云闪付 frontToken
     * <p>
     * {"resp":"00","msg":"成功","params":{"frontToken":"zOOrOQmURU2t7aJgUEDJxA==","expiresIn":7200}
     *
     * @return
     */
    public static String getFrontToken(String appid, String secret, StringRedisService redis) {
        if (redis.get("YunFrontToken") == null) {
            Map<String, String> sortedParams = new HashMap<>();
            sortedParams.put("appId", appid);
            sortedParams.put("secret", secret);
            // 16位随机字符串
            sortedParams.put("nonceStr", getRandomString(16));
            // 以秒为单位
            sortedParams.put("timestamp", System.currentTimeMillis() / 1000 + "");
            // 签名值，签名因子包括(appId,nonceStr, secret, timestamp)
            String signContent = getSignContent(sortedParams);
            // 删除secret
            sortedParams.remove("secret");
            // appId,nonceStr, secret, timestamp
            sortedParams.put("signature", sha256(signContent.getBytes()));
//        String strJson = new JSONObject(sortedParams).toString();
            String strJson = JSON.toJSONString(sortedParams);
            String result = postJson(URL, "application/json", strJson);
            log.info("获取云闪付frontToken===》" + result);
            JSONObject resultJson = JSON.parseObject(result);
//        JSONObject resultJson = new JSONObject(result);
            if ("00".equals(resultJson.get("resp"))) {
//            JSONObject paramsJson = new JSONObject(resultJson.get("params"));
                JSONObject paramsJson = JSON.parseObject(String.valueOf(resultJson.get("params")));
                String t = String.valueOf(paramsJson.get("frontToken"));
                Integer time = (Integer) paramsJson.get("expiresIn");
                time *= 1000;
                redis.set("YunFrontToken", t, time);
                return t;
            }
        } else {
            return String.valueOf(redis.get("YunFrontToken"));
        }
        return null;
    }

    public static String getFrontToken3(String appid, String secret1, StringRedisService redis) {
        if (redis.get("YunFrontToken") == null) {
            //应用Id
            String appId = appid;
            //秘钥
            String secret = secret1;

            //调用地址
            String url = URL;
            //拼装参数Map
            Map<String, String> params = new HashMap<String, String>(0);
            params.put("appId", appId);
            params.put("secret", secret);

            //生成随即字符串
            String nonceStr = Utils.createNonceStr();
            params.put("nonceStr", nonceStr);

            //生成时间戳
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            params.put("timestamp", timestamp);

            //签名
            String value = Utils.sortMap(params);
            String signature = Utils.sha256(value.getBytes());
            params.put("signature", signature);
            //仅用于加密，不上送字段
            params.remove("secret");
            //发送请求
            String resultStr = Utils.sendPostGson(url, params);
            JsonObject jsonObject = (JsonObject) new JsonParser().parse(resultStr);

            String t = jsonObject.get("params").getAsJsonObject().get("frontToken").getAsString();
//            String t = String.valueOf(paramsJson.get("frontToken"));
            Integer time = jsonObject.get("params").getAsJsonObject().get("expiresIn").getAsInt();
            time *= 1000;
            redis.set("YunFrontToken", t, time);
            return t;
        } else {
            return String.valueOf(redis.get("YunFrontToken"));
        }
    }

    /**
     * 生成指定长度的字符串
     *
     * @param length 字符串长度
     * @return
     */
    public static String getRandomString(int length) {
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(3);
            long result = 0;
            switch (number) {
                case 0:
                    result = Math.round(Math.random() * 25 + 65);
                    sb.append(String.valueOf((char) result));
                    break;
                case 1:
                    result = Math.round(Math.random() * 25 + 97);
                    sb.append(String.valueOf((char) result));
                    break;
                case 2:
                    sb.append(String.valueOf(new Random().nextInt(10)));
                    break;
            }
        }
        return sb.toString();
    }

    public static String getSignContent(Map<String, String> sortedParams) {
        StringBuffer content = new StringBuffer();
        List<String> keys = new ArrayList<>(sortedParams.keySet());
        Collections.sort(keys);
        int index = 0;
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = sortedParams.get(key);
            content.append((index == 0 ? "" : "&") + key + "=" + value);
            index++;
        }
        return content.toString();
    }

    public static String sha256(byte[] data) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            return bytesToHex(md.digest(data));
        } catch (Exception ex) {
            log.info("Never happen.", ex);
            return null;
        }
    }

    public static String bytesToHex(byte[] bytes) {
        String hexArray = "0123456789abcdef";
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            int bi = b & 0xff;
            sb.append(hexArray.charAt(bi >> 4));
            sb.append(hexArray.charAt(bi & 0xf));
        }
        return sb.toString();
    }

    public static String postJson(String generalUrl, String contentType, String params) {
        try {
            URL url = new URL(generalUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            // 设置通用的请求属性
            connection.setRequestProperty("Content-Type", contentType);
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setUseCaches(false);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 得到请求的输出流对象
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            out.write(params.getBytes("UTF-8"));
            out.flush();
            out.close();

            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> headers = connection.getHeaderFields();
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = null;
            in = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String result = "";
            String getLine;
            while ((getLine = in.readLine()) != null) {
                result += getLine;
            }
            in.close();
            return result;
        } catch (Exception e) {
            log.info("发送请求失败:异常信息：" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }


    public static String getFrontToken2(String appid, String secret1) {

        //应用Id
        String appId = appid;
        //秘钥
        String secret = secret1;

        //调用地址
        String url = "https://open.95516.com/open/access/1.0/frontToken";
        //拼装参数Map
        Map<String, String> params = new HashMap<String, String>(0);
        params.put("appId", appId);
        params.put("secret", secret);

        //生成随即字符串
        String nonceStr = Utils.createNonceStr();
        params.put("nonceStr", nonceStr);

        //生成时间戳
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        params.put("timestamp", timestamp);

        //签名
        String value = Utils.sortMap(params);
        String signature = Utils.sha256(value.getBytes());
        params.put("signature", signature);
        //仅用于加密，不上送字段
        params.remove("secret");
        //发送请求
        String resultStr = Utils.sendPostGson(url, params);
        return resultStr;
    }
}
